#include "StdAfx.h"
#include "TalkFlow.h"
#include "PlayVoiceNode.h"
#include "TinyServerDefine.h"
#include <fstream>

//xml file parse enginnes
#include <xercesc/parsers/XercesDOMParser.hpp>
#include <xercesc/dom/DOM.hpp>
#include <xercesc/sax/HandlerBase.hpp>
#include <xercesc/util/XMLString.hpp>
#include <xercesc/util/PlatformUtils.hpp>
#include <xercesc/framework/LocalFileFormatTarget.hpp>
#include <xercesc/framework/StdOutFormatTarget.hpp>

#include "v8.h"
#include "cproxyv8/cproxyv8-class.h"
#pragma comment(lib,"Winmm")


/*Handle<Value> talkIDGetter(Local<String> property,const AccessorInfo &info) 
{
	Local<Object> self = info.Holder();
	Local<External> wrap = Local<External>::Cast(self->GetInternalField(0));
	void* ptr = wrap->Value();
	return String::New(static_cast<IVRFlow::CTalkFlow*>(ptr)->m_talkIDStr,128);
}

void talkIDSetter(Local<String> property, Local<Value> value,const AccessorInfo& info) 
{
	Local<Object> self = info.Holder();
	Local<External> wrap = Local<External>::Cast(self->GetInternalField(0));
	void* ptr = wrap->Value();
	// static_cast<CTalkFlow*>(ptr)->m_talkIDStr = value->ToString();
}*/


namespace IVRFlow{

CTalkFlow::CTalkFlow(void)
: flowConfig(NULL)
, m_workThread(NULL)
{
}

CTalkFlow::~CTalkFlow(void)
{
}

bool CTalkFlow::StartFlow(string talkId)
{
	m_workThread = new TinyCC::CTinyThread( this, &CTalkFlow::flowThreadFunc,  (void*)this );
	m_talkID = talkId;
	return false;
}

bool CTalkFlow::readFlowFile(std::string filePath)
{
	/*std::ifstream ifile(filePath.c_str());

	std::string line;
	while( getline(ifile,line) )
	{    
		flow_Content.push_back(line);
	}
	return true;*/

	//parse xml flow file
	//init xml lib
	try {
		xercesc::XMLPlatformUtils::Initialize();
	}
	catch (const xercesc::XMLException& toCatch) {
		char* message = xercesc::XMLString::transcode(toCatch.getMessage());
		//MessageBox(NULL,message,"Exception message is:",MB_OK);
		xercesc::XMLString::release(&message);
		return false;
	}
	//XercesDOMParser*
	xercesc::DOMTreeWalker * m_walker;
	xercesc::DOMDocument * m_doc;
	xercesc::XercesDOMParser *m_parser = new xercesc::XercesDOMParser();
	m_parser->setValidationScheme(xercesc::XercesDOMParser::Val_Always);	  // optional.
	m_parser->setDoNamespaces(true);	  // optional

	try {
		m_parser->parse(const_cast<char *>(filePath.c_str()));
		//log
		//		logfile<<"version.xml file parsed pass"<<std::endl;
		m_doc=m_parser->getDocument();
		m_walker = 
			m_doc->createTreeWalker((xercesc::DOMNode*)m_doc->getDocumentElement(), xercesc::DOMNodeFilter::SHOW_ELEMENT, NULL, true);

	}
	catch (const xercesc::XMLException& toCatch) {
		char* message = xercesc::XMLString::transcode(toCatch.getMessage());
		//MessageBox(NULL,message,"Exception message is:",MB_OK);
		//strTime = CTime::GetCurrentTime().Format("%Y-%m-%d-%a  %H:%M:%S");
		//logfile<<"XML Parse Error:"<<message<<"at:"<<strTime<<std::endl;
		xercesc::XMLString::release(&message);
		return false;
	}
	catch (const xercesc::DOMException& toCatch) {
		char* message = xercesc::XMLString::transcode(toCatch.msg);
		//MessageBox(NULL,message,"Exception message is:",MB_OK);
		//strTime = CTime::GetCurrentTime().Format("%Y-%m-%d-%a  %H:%M:%S");
		//logfile<<"XML Parse Error:"<<message<<"at:"<<strTime<<std::endl;
		xercesc::XMLString::release(&message);
		return false;
	}
	catch (...) {
		//MessageBox(NULL,"Setting File Task.xml Read Error\n","Exception message is:",MB_OK);
		//strTime = CTime::GetCurrentTime().Format("%Y-%m-%d-%a  %H:%M:%S");
		//logfile<<"XML Parse Error:"<<"at:"<<strTime<<std::endl;
		return false;
	}

	//read file content
	//read file in here
	try{
		xercesc::DOMNode *current2 = m_walker->getCurrentNode();
		//current2=walker->nextNode();
		std::string name(xercesc::XMLString::transcode(current2->getNodeName()));

		if(name=="CCVoiceCard")
		{

			for(current2=m_walker->nextNode();current2!=0;current2=m_walker->nextNode())
			{
				//read setting
				name = xercesc::XMLString::transcode(current2->getNodeName());
				/*if(name==std::string("Instance"))
				{
					current2=m_walker->nextNode();
					if(current2==0)
						break;
					name = xercesc::XMLString::transcode(current2->getNodeName());
					if(name == "Name")
						this->m_InstanceName = xercesc::XMLString::transcode(((xercesc::DOMElement*)current2)->getTextContent());

					current2=m_walker->nextNode();
					if(current2==0)
						break;
					name = xercesc::XMLString::transcode(current2->getNodeName());
					if(name == "ModuleIP")
						m_ModuleIP = xercesc::XMLString::transcode(((xercesc::DOMElement*)current2)->getTextContent());

					current2=m_walker->nextNode();
					if(current2==0)
						break;
					name = xercesc::XMLString::transcode(current2->getNodeName());
					if(name == "ModulePort")
						m_ModulePort = atoi(xercesc::XMLString::transcode(((xercesc::DOMElement*)current2)->getTextContent()));

					current2=m_walker->nextNode();
					if(current2==0)
						break;
					name = xercesc::XMLString::transcode(current2->getNodeName());
					if(name == "ServerIP")
						m_ServerIP = xercesc::XMLString::transcode(((xercesc::DOMElement*)current2)->getTextContent());

					current2=m_walker->nextNode();
					if(current2==0)
						break;
					name = xercesc::XMLString::transcode(current2->getNodeName());
					if(name == "ServerPort")
						m_ServerPort = atoi(xercesc::XMLString::transcode(((xercesc::DOMElement*)current2)->getTextContent()));


				}

				name = xercesc::XMLString::transcode(current2->getNodeName());
				if(name==std::string("Hardware"))
				{
					current2=m_walker->nextNode();
					if(current2==0)
						break;
					name = xercesc::XMLString::transcode(current2->getNodeName());
					if(name == "CardType")
						this->m_CardType = xercesc::XMLString::transcode(((xercesc::DOMElement*)current2)->getTextContent());
				}*/
			}
		}

	}
	catch(...)
	{
		//		strTime = CTime::GetCurrentTime().Format("%Y-%m-%d-%a  %H:%M:%S"); 
		//MessageBox ("Parse xml file Error");
		//closeXmLFile();
	}
	//end read 

	//close xml file
	m_doc->release();
	try {
		xercesc::XMLPlatformUtils::Terminate();
	}
	catch (const xercesc::XMLException& toCatch) {
		char* message = xercesc::XMLString::transcode(toCatch.getMessage());
		//MessageBox(NULL,message,"Exception message is:",MB_OK);
		xercesc::XMLString::release(&message);
		return false;
	}
	return true;
	
}

//actually work function
void CTalkFlow::flowThreadFunc(void* param)
{
	/*v8::HandleScope handle_scope;

	// Create a template for the global object.
	v8::Handle<v8::ObjectTemplate> global = v8::ObjectTemplate::New();

	CPROXYV8_METHOD_ID(CPlayVoiceNode,Enter, enter);
	CPROXYV8_METHOD_ID(CPlayVoiceNode,Leave, leave);
	CPROXYV8_METHOD_ID(CPlayVoiceNode,setFilePath, setFilePath);

	//expose flow object to js
	Handle<ObjectTemplate> talkFlow_templ = ObjectTemplate::New() ;
	talkFlow_templ->SetInternalFieldCount(1);
	talkFlow_templ->SetAccessor(String::New("TalkID"),talkIDGetter,talkIDSetter);
	Handle<Object> talkFlow_object = talkFlow_templ->NewInstance() ; 
	talkFlow_object->SetInternalField(0, External::New(static_cast<CTalkFlow *>(this)));
	//talkFlow_templ->SetNamedPropertyHandler();b
	global->Set(String::New("Flow"),talkFlow_object);
	//end expose flow object to js

	global->Set(v8::String::New("PlayVoiceNode"), CPROXYV8_CLASS(CPlayVoiceNode)->GetFunctionTemplate()); // add Point to JS

	std::string filepath = "C:\\TinyApp\\TinyCC\\VoiceScript\\welcome.lccs";

	if(readFlowFile(filepath) == false)
	{
		g_Logger.log(debug1,"Log file "+filepath+"read error");
		return;
	}

	v8::Handle<v8::Context> context = v8::Context::New(NULL, global);
	// Enter the newly created execution environment.
	v8::Context::Scope context_scope(context);

	// Create a string containing the JavaScript source code. 
	Handle<String> source = String::New("");

	//function declaration is needed, any code before main should be compiler and run once


	for(int i = 0; i < flow_Content.size(); ++i)
	{

		// Create a string containing the JavaScript source code. 
		source = String::New(flow_Content[i].c_str());
		// Compile the source code. 
		Handle<Script> script = Script::Compile(source);
		// Run the script to get the result. 
		Handle<Value> result = script->Run();
	}*/

	//read xml file

	//parse all variable in flow

	//parse xml file,construct class for all node and push to list

	//execute the ivr, execute all node from frist to end in list

	if(NodeVector.size()<=0)
			return;

	for(int i = 0; i<NodeVector.size();)
	{
		if(m_currentNode->GetNextNodeName() == "")
		{
			m_currentNode = NodeVector[i++];
		}
		else
		{
			//find node by nodeName
		}
		m_currentNode->Enter();
		//wait event for something happened,like key down, phone hooked....
		m_currentNode->Leave();
	}
	
	//clean and exit
}

void CTalkFlow::ExecuteJScript(std::vector<string>& sourceCode)
{
	return ;
}

void CTalkFlow::UpdateFlowVar(string key,CIVRNode * value)
{

}

void CTalkFlow::UpdateFlowVar(string key, string value)
{

}

void CTalkFlow::UpdateFlowVar(string key, int value)
{

}

CIVRNode*CTalkFlow::GetFlowVar(string key)
{
	return NULL;
}

void CTalkFlow::FlowExceptioned(int errCode,std::string errMsg)
{
	m_currentNode->Terminate();
	//log errmsg and exit;
	return;
}

void  CTalkFlow::ProcessReceivedMsg(CTinyMsg& inMsg,CTinyMsg& OutMsg)
{
	if(inMsg.getMsgIndex() == VOICECARD_ACTION)
	{
		/*switch (inMsg.getMsgItem())
		{
		case VOICECARD_RECEIVEDKEY:
			{
				if(flow.isStated() == true)
				{
					m_currentNode.processKeyRecived(key);
					UpdateFlowVar("ReceivedKey",key);
				}
				else
					g_Logger.log(debug1,"flow has not been started!")

			}break;
		default:
			break;
		}*/
	}
}

void CTalkFlow::TerminateFlow(void)
{
	m_workThread->forceExit();
}

void CTalkFlow::EndFlow(void)
{
	m_workThread->normalExit();
}
}